home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / c / ibmcom_c.zip / IBMCOM.C < prev    next >
C/C++ Source or Header  |  1989-10-18  |  22KB  |  500 lines

  1. /*****************************************************************************
  2.  *                   ibmcom.c                     *
  3.  *****************************************************************************
  4.  * DESCRIPTION:    This file contains a set of routines for doing low-level     *
  5.  *        serial communications on the IBM PC.  It was translated         *
  6.  *        directly from Wayne Conrad's IBMCOM.PAS version 3.1, with    *
  7.  *        the goal of near-perfect functional correspondence between   *
  8.  *        the Pascal and C versions.                     *
  9.  *                                         *
  10.  * REVISIONS:    18 OCT 89 - RAC - Original translation from IBMCOM.PAS, with *
  11.  *                  liberal plagiarism of comments from the    *
  12.  *                  Pascal.                     *
  13.  *****************************************************************************/
  14.  
  15. #include    <stdio.h>
  16. #include    <dos.h>
  17. #include    "ibmcom.h"
  18.  
  19. /*****************************************************************************
  20.  *                   8250 Definitions                     *
  21.  *****************************************************************************/
  22.  
  23. /*      Offsets to various 8250 registers.  Taken from IBM Technical         */
  24. /*      Reference Manual, p. 1-225                                           */
  25.  
  26. #define TXBUFF  0                       /* Transmit buffer register */
  27. #define RXBUFF  0                       /* Receive buffer register */
  28. #define DLLSB   0                       /* Divisor latch LS byte */
  29. #define DLMSB   1                       /* Divisor latch MS byte */
  30. #define IER     1                       /* Interrupt enable register */
  31. #define IIR     2                       /* Interrupt ID register */
  32. #define LCR     3                       /* Line control register */
  33. #define MCR     4                       /* Modem control register */
  34. #define LSR     5                       /* Line status register */
  35. #define MSR     6                       /* Modem status register */
  36.  
  37. /*      Modem control register bits                                          */
  38.  
  39. #define DTR     0x01                    /* Data terminal ready */
  40. #define RTS     0x02                    /* Request to send */
  41. #define OUT1    0x04                    /* Output #1 */
  42. #define OUT2    0x08                    /* Output #2 */
  43. #define LPBK    0x10                    /* Loopback mode bit */
  44.  
  45. /*      Modem status register bits                                           */
  46.  
  47. #define DCTS    0x01                    /* Delta clear to send */
  48. #define DDSR    0x02                    /* Delta data set ready */
  49. #define TERI    0x04                    /* Trailing edge ring indicator */
  50. #define DRLSD   0x08                    /* Delta Rx line signal detect */
  51. #define CTS     0x10                    /* Clear to send */
  52. #define DSR     0x20                    /* Data set ready */
  53. #define RI      0x40                    /* Ring indicator */
  54. #define RLSD    0x80                    /* Receive line signal detect */
  55.  
  56. /*      Line control register bits                                           */
  57.  
  58. #define DATA5   0x00                    /* 5 Data bits */
  59. #define DATA6   0x01                    /* 6 Data bits */
  60. #define DATA7   0x02                    /* 7 Data bits */
  61. #define DATA8   0x03                    /* 8 Data bits */
  62.  
  63. #define STOP1   0x00                    /* 1 Stop bit */
  64. #define STOP2   0x04                    /* 2 Stop bits */
  65.  
  66. #define NOPAR   0x00                    /* No parity */
  67. #define ODDPAR  0x08                    /* Odd parity */
  68. #define EVNPAR  0x18                    /* Even parity */
  69. #define STKPAR  0x28                    /* Stick parity */
  70. #define ZROPAR    0x38            /* Zero parity */
  71.  
  72. /*      Line status register bits                                            */
  73.  
  74. #define RDR     0x01                    /* Receive data ready */
  75. #define ERRS    0x1E                    /* All the error bits */
  76. #define TXR     0x20                    /* Transmitter ready */
  77.  
  78. /*      Interrupt enable register bits                                       */
  79.  
  80. #define DR      0x01                    /* Data ready */
  81. #define THRE    0x02                    /* Tx buffer empty */
  82. #define RLS     0x04                    /* Receive line status */
  83.  
  84. /*****************************************************************************
  85.  *                   Names for Numbers                 *
  86.  *****************************************************************************/
  87.  
  88. #define MAX_PORT    4
  89.  
  90. #define TRUE        1
  91. #define FALSE        0
  92.  
  93. /*****************************************************************************
  94.  *                  Global Data                     *
  95.  *****************************************************************************/
  96.  
  97. /*  UART i/o addresses.  Values depend upon which COMM port is selected  */
  98.  
  99. int    uart_data;        /* Data register */
  100. int    uart_ier;        /* Interrupt enable register */
  101. int    uart_iir;        /* Interrupt identification register */
  102. int    uart_lcr;        /* Line control register */
  103. int    uart_mcr;        /* Modem control register */
  104. int    uart_lsr;        /* Line status register */
  105. int    uart_msr;        /* Modem status register */
  106.  
  107. char    com_installed;        /* Flag: Communications routines installed */
  108. int    intnum;            /* Interrupt vector number for chosen port */
  109. char    i8259bit;        /* 8259 bit mask */
  110. char    old_i8259_mask;        /* Copy as it was when we were called */
  111. char    old_ier;        /* Modem register contents saved for */
  112. char    old_mcr;        /*  restoring when we're done */
  113. void interrupt (*old_vector)();    /* Place to save COM1 vector */
  114.  
  115. /*  Transmit queue.  Characters to be transmitted are held here until the  */
  116. /*  UART is ready to transmit them.  */
  117.  
  118. #define TX_QUEUE_SIZE    16    /* Transmit queue size.  Change to suit */
  119.  
  120. char    tx_queue[TX_QUEUE_SIZE];
  121. int    tx_in;            /* Index of where to store next character */
  122. int    tx_out;            /* Index of where to retrieve next character */
  123. int    tx_chars;        /* Count of characters in queue */
  124.  
  125. /*  Receive queue.  Received characters are held here until retrieved by  */
  126. /*  com_rx()  */
  127.  
  128. #define RX_QUEUE_SIZE    4096    /* Receive queue size.  Change to suit */
  129.  
  130. char    rx_queue[RX_QUEUE_SIZE];
  131. int    rx_in;            /* Index of where to store next character */
  132. int    rx_out;            /* Index of where to retrieve next character */
  133. int    rx_chars;        /* Count of characters in queue */
  134.  
  135. /*****************************************************************************
  136.  *                 com_install()                     *
  137.  *****************************************************************************
  138.  * DESCRIPTION:    Installs the communications drivers.                 *
  139.  *                                         *
  140.  * SYNOPSIS:    status = com_install(int portnum);                 *
  141.  *        int    portnum;    Desired port number             *
  142.  *        int    status;        0 = Successful installation         *
  143.  *                    1 = Invalid port number                *
  144.  *                    2 = No UART for specified port         *
  145.  *                    3 = Drivers already installed         *
  146.  *                                         *
  147.  * REVISIONS:    18 OCT 89 - RAC - Translated from IBMCOM.PAS             *
  148.  *****************************************************************************/
  149.  
  150. const int    uart_base[] =    { 0x3F8, 0x2F8, 0x3E8, 0x2E8 };
  151. const char    intnums[] =    { 0x0C,  0x0B,  0x0C,  0x0B };
  152. const char    i8259levels[] =    { 4,     3,     4,     3 };
  153.  
  154. int com_install(int portnum) {
  155.  
  156.     if (com_installed)                /* Drivers already installed */
  157.     return 3;
  158.     if ((portnum < 1) || (portnum > MAX_PORT))    /* Port number out of bounds */
  159.     return 1;
  160.  
  161.     uart_data = uart_base[portnum-1];        /* Set UART I/O addresses */
  162.     uart_ier  = uart_data + IER;        /*  for the selected comm */
  163.     uart_iir  = uart_data + IIR;        /*  port */
  164.     uart_lcr  = uart_data + LCR;
  165.     uart_mcr  = uart_data + MCR;
  166.     uart_lsr  = uart_data + LSR;
  167.     uart_msr  = uart_data + MSR;
  168.     intnum    = intnums[portnum-1];        /* Ditto for interrupt */
  169.     i8259bit  = 1 << i8259levels[portnum-1];    /*  vector and 8259 bit mask */
  170.  
  171.     old_ier = inportb(uart_ier);        /* Return an error if we */
  172.     outportb(uart_ier, 0);            /*  can't access the UART */
  173.     if (inportb(uart_ier) != 0)
  174.     return 2;
  175.  
  176.     disable();                    /* Save the original 8259 */
  177.     old_i8259_mask = inportb(0x21);        /*  mask, then disable the */
  178.     outportb(0x21, old_i8259_mask | i8259bit);    /*  8259 for this interrupt */
  179.     enable();
  180.  
  181.     com_flush_